package concurrency;

import java.util.concurrent.BrokenBarrierException;

public abstract class Robot implements Runnable {
    private RobotPool mPool;

    private boolean mEngage = false;

    protected Assembler mAssembler;

    public Robot(RobotPool p) {
        mPool = p;
    }

    /**
     * 下电
     */
    private synchronized void powerDown() throws InterruptedException {
        mEngage = false;
        // Disconnect from the Assembler
        // Put ourselves back in the available pool
        mAssembler = null;
        // Put ourselves back in the available pool
        mPool.release(this);
        // Power down
        while (!mEngage) {
            wait();
        }
    }

    public Robot assignAssembler(Assembler assembler) {
        mAssembler = assembler;
        return this;
    }

    /**
     * carry out or participate in an activity
     */
    public synchronized void engage() {
        mEngage = true;
        notifyAll();
    }

    /**
     * The part of run() that's different for each robot
     */
    abstract protected void performService();

    @Override
    public void run() {
        try {
            // Wait until needed
            powerDown();
            while (!Thread.interrupted()) {
                performService();
                // Synchronize
                mAssembler.barrier().await();
                // We're done with that job...
                powerDown();
            }
        } catch (InterruptedException e) {
            System.out.println("Exiting " + this + " via interrupt");
            // e.printStackTrace();
        } catch (BrokenBarrierException e) {
            // This one we want to know about
            e.printStackTrace();
        }
        System.out.println(this + " off");
    }

    @Override
    public String toString() {
        return getClass().getName();
    }
}
